House Price - Data Prep
House Price - Data Prep
- 1 Objetivos
- 2 Conjunto de Dados
- 3 Conhecendo as caracteristicas dos dados
- 4 Separando o conjunto de dados pelo tipo.
- 5 Data Profiling
- 6 Selecionando Variáveis
- 7 Juntandos os data frames
- 8 Removendo valores nulos das linhas
- 9 Dados de teste
- 10 Selecionando as variáveis
- 11 Separando o conjunto de dados de teste pelo tipo.
- 12 Juntandos os data frames
- 13 Removendo valores nulos das linhas
- 14 Exportando os dados limpos
1 Objetivos
- Número de variáveis: 81
- Tipo de variáveis
- Inteiras ou discretas:
- Numéricas ou double
- Categóricas
- Qualitativas
- Qualidade dos dados
- Quantidade de NA’s por variável
- Criação de novas variáveis, se precisar
- Transformação das variáveis, se precisar
2 Conjunto de Dados
O dataprep será realizado considerando que os dados de treinamento e de teste foram amostrados de tal forma que as proporções de valores assumidos por cada variável estão equilibradas nas duas amostras.
2.1 Dados de treinamento
# Read table
df.train <- data.table::fread('../dados/train.csv',
sep=",",
showProgress = FALSE) %>%
data.frame(stringsAsFactors = F)
df.train3 Conhecendo as caracteristicas dos dados
str(df.train)## 'data.frame': 1460 obs. of 81 variables:
## $ Id : int 1 2 3 4 5 6 7 8 9 10 ...
## $ MSSubClass : int 60 20 60 70 60 50 20 60 50 190 ...
## $ MSZoning : chr "RL" "RL" "RL" "RL" ...
## $ LotFrontage : int 65 80 68 60 84 85 75 NA 51 50 ...
## $ LotArea : int 8450 9600 11250 9550 14260 14115 10084 10382 6120 7420 ...
## $ Street : chr "Pave" "Pave" "Pave" "Pave" ...
## $ Alley : chr NA NA NA NA ...
## $ LotShape : chr "Reg" "Reg" "IR1" "IR1" ...
## $ LandContour : chr "Lvl" "Lvl" "Lvl" "Lvl" ...
## $ Utilities : chr "AllPub" "AllPub" "AllPub" "AllPub" ...
## $ LotConfig : chr "Inside" "FR2" "Inside" "Corner" ...
## $ LandSlope : chr "Gtl" "Gtl" "Gtl" "Gtl" ...
## $ Neighborhood : chr "CollgCr" "Veenker" "CollgCr" "Crawfor" ...
## $ Condition1 : chr "Norm" "Feedr" "Norm" "Norm" ...
## $ Condition2 : chr "Norm" "Norm" "Norm" "Norm" ...
## $ BldgType : chr "1Fam" "1Fam" "1Fam" "1Fam" ...
## $ HouseStyle : chr "2Story" "1Story" "2Story" "2Story" ...
## $ OverallQual : int 7 6 7 7 8 5 8 7 7 5 ...
## $ OverallCond : int 5 8 5 5 5 5 5 6 5 6 ...
## $ YearBuilt : int 2003 1976 2001 1915 2000 1993 2004 1973 1931 1939 ...
## $ YearRemodAdd : int 2003 1976 2002 1970 2000 1995 2005 1973 1950 1950 ...
## $ RoofStyle : chr "Gable" "Gable" "Gable" "Gable" ...
## $ RoofMatl : chr "CompShg" "CompShg" "CompShg" "CompShg" ...
## $ Exterior1st : chr "VinylSd" "MetalSd" "VinylSd" "Wd Sdng" ...
## $ Exterior2nd : chr "VinylSd" "MetalSd" "VinylSd" "Wd Shng" ...
## $ MasVnrType : chr "BrkFace" "None" "BrkFace" "None" ...
## $ MasVnrArea : int 196 0 162 0 350 0 186 240 0 0 ...
## $ ExterQual : chr "Gd" "TA" "Gd" "TA" ...
## $ ExterCond : chr "TA" "TA" "TA" "TA" ...
## $ Foundation : chr "PConc" "CBlock" "PConc" "BrkTil" ...
## $ BsmtQual : chr "Gd" "Gd" "Gd" "TA" ...
## $ BsmtCond : chr "TA" "TA" "TA" "Gd" ...
## $ BsmtExposure : chr "No" "Gd" "Mn" "No" ...
## $ BsmtFinType1 : chr "GLQ" "ALQ" "GLQ" "ALQ" ...
## $ BsmtFinSF1 : int 706 978 486 216 655 732 1369 859 0 851 ...
## $ BsmtFinType2 : chr "Unf" "Unf" "Unf" "Unf" ...
## $ BsmtFinSF2 : int 0 0 0 0 0 0 0 32 0 0 ...
## $ BsmtUnfSF : int 150 284 434 540 490 64 317 216 952 140 ...
## $ TotalBsmtSF : int 856 1262 920 756 1145 796 1686 1107 952 991 ...
## $ Heating : chr "GasA" "GasA" "GasA" "GasA" ...
## $ HeatingQC : chr "Ex" "Ex" "Ex" "Gd" ...
## $ CentralAir : chr "Y" "Y" "Y" "Y" ...
## $ Electrical : chr "SBrkr" "SBrkr" "SBrkr" "SBrkr" ...
## $ X1stFlrSF : int 856 1262 920 961 1145 796 1694 1107 1022 1077 ...
## $ X2ndFlrSF : int 854 0 866 756 1053 566 0 983 752 0 ...
## $ LowQualFinSF : int 0 0 0 0 0 0 0 0 0 0 ...
## $ GrLivArea : int 1710 1262 1786 1717 2198 1362 1694 2090 1774 1077 ...
## $ BsmtFullBath : int 1 0 1 1 1 1 1 1 0 1 ...
## $ BsmtHalfBath : int 0 1 0 0 0 0 0 0 0 0 ...
## $ FullBath : int 2 2 2 1 2 1 2 2 2 1 ...
## $ HalfBath : int 1 0 1 0 1 1 0 1 0 0 ...
## $ BedroomAbvGr : int 3 3 3 3 4 1 3 3 2 2 ...
## $ KitchenAbvGr : int 1 1 1 1 1 1 1 1 2 2 ...
## $ KitchenQual : chr "Gd" "TA" "Gd" "Gd" ...
## $ TotRmsAbvGrd : int 8 6 6 7 9 5 7 7 8 5 ...
## $ Functional : chr "Typ" "Typ" "Typ" "Typ" ...
## $ Fireplaces : int 0 1 1 1 1 0 1 2 2 2 ...
## $ FireplaceQu : chr NA "TA" "TA" "Gd" ...
## $ GarageType : chr "Attchd" "Attchd" "Attchd" "Detchd" ...
## $ GarageYrBlt : int 2003 1976 2001 1998 2000 1993 2004 1973 1931 1939 ...
## $ GarageFinish : chr "RFn" "RFn" "RFn" "Unf" ...
## $ GarageCars : int 2 2 2 3 3 2 2 2 2 1 ...
## $ GarageArea : int 548 460 608 642 836 480 636 484 468 205 ...
## $ GarageQual : chr "TA" "TA" "TA" "TA" ...
## $ GarageCond : chr "TA" "TA" "TA" "TA" ...
## $ PavedDrive : chr "Y" "Y" "Y" "Y" ...
## $ WoodDeckSF : int 0 298 0 0 192 40 255 235 90 0 ...
## $ OpenPorchSF : int 61 0 42 35 84 30 57 204 0 4 ...
## $ EnclosedPorch: int 0 0 0 272 0 0 0 228 205 0 ...
## $ X3SsnPorch : int 0 0 0 0 0 320 0 0 0 0 ...
## $ ScreenPorch : int 0 0 0 0 0 0 0 0 0 0 ...
## $ PoolArea : int 0 0 0 0 0 0 0 0 0 0 ...
## $ PoolQC : chr NA NA NA NA ...
## $ Fence : chr NA NA NA NA ...
## $ MiscFeature : chr NA NA NA NA ...
## $ MiscVal : int 0 0 0 0 0 700 0 350 0 0 ...
## $ MoSold : int 2 5 9 2 12 10 8 11 4 1 ...
## $ YrSold : int 2008 2007 2008 2006 2008 2009 2007 2009 2008 2008 ...
## $ SaleType : chr "WD" "WD" "WD" "WD" ...
## $ SaleCondition: chr "Normal" "Normal" "Normal" "Abnorml" ...
## $ SalePrice : int 208500 181500 223500 140000 250000 143000 307000 200000 129900 118000 ...
Nosso conjunto de dados apresenta somente dois tipos de dados, além disso a primeira vista há muitos dados faltantes ou nulos.
4 Separando o conjunto de dados pelo tipo.
tipo <- lapply(df.train,class)4.1 Dados tipo inteiro
df.int <- df.train[,unlist(tipo) %in% "integer"]
df.int4.2 Dados tipo string
df.str <- df.train[,unlist(tipo) %in% "character"]
df.str4.3 Tranformando dados tipo string em categorical.
Afim de medir a influência que determinado valor de uma variável string exerce sobre a variável resposta, iremos tranformá-las em variável categórica.
df.cat <- lapply(df.str,factor) %>% data.frame()
df.cat5 Data Profiling
5.1 Tipo inteiro: % de valores nulos
apply(is.na(df.int),2,
function(x) round(100*sum(as.numeric(x))/length(x),2)) %>%
sort(decreasing = T)## LotFrontage GarageYrBlt MasVnrArea Id MSSubClass
## 17.74 5.55 0.55 0.00 0.00
## LotArea OverallQual OverallCond YearBuilt YearRemodAdd
## 0.00 0.00 0.00 0.00 0.00
## BsmtFinSF1 BsmtFinSF2 BsmtUnfSF TotalBsmtSF X1stFlrSF
## 0.00 0.00 0.00 0.00 0.00
## X2ndFlrSF LowQualFinSF GrLivArea BsmtFullBath BsmtHalfBath
## 0.00 0.00 0.00 0.00 0.00
## FullBath HalfBath BedroomAbvGr KitchenAbvGr TotRmsAbvGrd
## 0.00 0.00 0.00 0.00 0.00
## Fireplaces GarageCars GarageArea WoodDeckSF OpenPorchSF
## 0.00 0.00 0.00 0.00 0.00
## EnclosedPorch X3SsnPorch ScreenPorch PoolArea MiscVal
## 0.00 0.00 0.00 0.00 0.00
## MoSold YrSold SalePrice
## 0.00 0.00 0.00
De forma geral podemos concluir que não há muitos valores nulos para as variáveis do tipo inteiro, sendo que apenas a variável LotFrontage apresenta cerca de 17.74 % de valores ausentes, mais adiante iremos decidir se está variável permanece ou será retirada de nosso conjunto de dados.
Obs.: Pode ser que seja possível através da média, mediana, knn e outra técnica imputar valores na variável LotFrontage, afim de preencher seus valores nulos.
5.2 Tipo Categorical: % de valores nulos
missing <- apply(is.na(df.cat),2,function(x){
nulos <-100*sum(as.numeric(x))/length(x)
round(nulos,2)
}) %>%
sort(decreasing = T)
missing## PoolQC MiscFeature Alley Fence FireplaceQu
## 99.52 96.30 93.77 80.75 47.26
## GarageType GarageFinish GarageQual GarageCond BsmtExposure
## 5.55 5.55 5.55 5.55 2.60
## BsmtFinType2 BsmtQual BsmtCond BsmtFinType1 MasVnrType
## 2.60 2.53 2.53 2.53 0.55
## Electrical MSZoning Street LotShape LandContour
## 0.07 0.00 0.00 0.00 0.00
## Utilities LotConfig LandSlope Neighborhood Condition1
## 0.00 0.00 0.00 0.00 0.00
## Condition2 BldgType HouseStyle RoofStyle RoofMatl
## 0.00 0.00 0.00 0.00 0.00
## Exterior1st Exterior2nd ExterQual ExterCond Foundation
## 0.00 0.00 0.00 0.00 0.00
## Heating HeatingQC CentralAir KitchenQual Functional
## 0.00 0.00 0.00 0.00 0.00
## PavedDrive SaleType SaleCondition
## 0.00 0.00 0.00
Veja que as variáveis PoolQC, MiscFeature, Alley, Fence e FireplaceQu não nos deixam outra alternativa senão a remoção delas do conjunto de dados, pois neste caso, a imputação de dados seria um grande problema na propagação do erro considerando as incertezas associadas aos métodos de imputação.
6 Selecionando Variáveis
Dos resultados acima iremos retirar de nosso conjunto de dados algumas variáveis.
6.1 Selecão de Variável tipo inteiro:
- LotFrontage (retiramos por questões de tempo)
df.int <- df.int %>%
select(-LotFrontage)
df.int6.2 Selecão de Variável Tipo Sring:
- PoolQC
- MiscFeature
- Alley
- Fence
- FireplaceQu
df.cat <- df.cat %>%
select(-PoolQC,-MiscFeature,
-Alley,-Fence,-FireplaceQu)
df.cat7 Juntandos os data frames
Jutando os dados tipo inteiros e string.
df.train <- bind_cols(df.int,df.cat)
df.train8 Removendo valores nulos das linhas
Nosso df.train possui 1460 linhas. Se removermos os valores nulos das linhas será que ainda teremos volume de dados significativo ? Ou seja, qual a porcentagem de valores nulos nas linhas ?
paste(round(100*(1-(nrow(na.omit(df.train))/nrow(df.train))),2),"%")## [1] "8.36 %"
Com 8.36 % ainda nos sobre mais de 90% dos dados para análise, dessa forma removeremos os valores nulos das linhas.
df.train <- na.omit(df.train)
df.trainAgora com 1338 linhas nosso df.train encontra-se limpo e pronto para ser explorado.
9 Dados de teste
Iremos realizar nos dados de teste as mesmas transformações aplicadas aos dados de treino.
df.test <- data.table::fread('../dados/test.csv',
sep=",",
showProgress = FALSE) %>%
data.frame(stringsAsFactors = F)
df.test10 Selecionando as variáveis
Removendo as mesmas variáveis do conjunto de treinamento.
df.test <- df.test %>%
select(-LotFrontage,-PoolQC,
-MiscFeature,-Alley,
-Fence,-FireplaceQu)11 Separando o conjunto de dados de teste pelo tipo.
tipo <- lapply(df.test,class)11.1 Dados tipo inteiro
test.int <- df.test[,unlist(tipo) %in% "integer"]
test.int11.2 Dados tipo string
test.str <- df.test[,unlist(tipo) %in% "character"]
test.str11.3 Tranformando dados tipo string em categorical.
test.cat <- lapply(test.str,factor) %>% data.frame()
test.cat12 Juntandos os data frames
Jutando os dados tipo inteiros e string.
df.test <- bind_cols(test.int,test.cat)
df.test13 Removendo valores nulos das linhas
Nosso df.train possui 1459 linhas. Se removermos os valores nulos das linhas será que ainda teremos volume de dados significativo ? Ou seja, qual a porcentagem de valores nulos nas linhas ?
paste(round(100*(1-(nrow(na.omit(df.test))/nrow(df.test))),2),"%")## [1] "9.6 %"
Com 9.6 % ainda nos sobre mais de 90% dos dados para análise, dessa forma removeremos os valores nulos das linhas.
df.test <- na.omit(df.test)
df.testAgora com 1319 linhas nosso df.test encontra-se limpo e pronto para ser explorado.
14 Exportando os dados limpos
write.csv(df.train,'../outputs/df.train.csv')
write.csv(df.test,'../outputs/df.test.csv')